/**
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.rtmp.sample.slice;

import com.rtmp.librtmp.RtmpUtil;
import com.rtmp.sample.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.data.DatabaseHelper;
import ohos.data.preferences.Preferences;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.io.File;

public class MainAbilitySlice extends AbilitySlice {

    private static final String TAG = "RTMP";
    /**
     * Preferences文件名称
     */
    private static final String PREF_NAME = "rtmp_server";
    /**
     * Preferences文件Key值，该值表示服务器地址
     */
    private static final String KEY_SERVER = "key_server";
    /**
     * 拉流的结果保存在本地的文件名称
     */
    private static final String FILENAME = "video_receive.flv";

    private static final int EVENT_ID_RECEIVE_START = 1;
    private static final int EVENT_ID_RECEIVE_FINISH = 2;
    private static final int EVENT_ID_PUSH_START = 3;
    private static final int EVENT_ID_PUSH_END = 4;

    private final HiLogLabel rtmpLabel = new HiLogLabel(HiLog.LOG_APP, 0, TAG);
    private final EventHandler mainHanlder = new EventHandler(EventRunner.getMainEventRunner()) {
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            switch (event.eventId) {
                case EVENT_ID_RECEIVE_START:
                    textReceiveStatus.setText(getString(ResourceTable.String_receive_status, "拉流中..."));
                    break;
                case EVENT_ID_RECEIVE_FINISH:
                    if (event.object instanceof Boolean) {
                        boolean value = (boolean) event.object;
                        textReceiveStatus.setText(getString(ResourceTable.String_receive_status, value ? "拉流成功" : "拉流失败"));
                    }
                    break;
                case EVENT_ID_PUSH_START:
                    textPushStatus.setText(getString(ResourceTable.String_push_status, "推流中..."));
                    break;
                case EVENT_ID_PUSH_END:
                    if (event.object instanceof Boolean) {
                        boolean value = (boolean) event.object;
                        textPushStatus.setText(getString(ResourceTable.String_push_status, value ? "推流成功" : "推流失败"));
                    }
                    break;
                default:
                    break;
            }
        }
    };

    private TaskDispatcher globalTaskDispatcher;
    private Preferences preferences;
    private Text textReceiveStatus;
    private Text textPushStatus;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
        if (globalTaskDispatcher == null) {
            showToast("GlobalTaskDispatcher is null.");
        }

        Text textVersion = (Text) findComponentById(ResourceTable.Id_textVersionResult);
        textVersion.setText(RtmpUtil.getRtmpVersion());

        textReceiveStatus = (Text) findComponentById(ResourceTable.Id_textReceiveStatus);
        findComponentById(ResourceTable.Id_btnReceive).setClickedListener(component -> {
            String rtmp = getRtmpAddress();
            if (!checkIpValid(rtmp)) {
                showToast("rtmp服务地址不正确，请保存正确的地址");
                return;
            }
            if (checkPermission("ohos.permission.INTERNET") && checkPermission("ohos.permission.WRITE_USER_STORAGE")) {
                log("permission was granted");
                globalTaskDispatcher.asyncDispatch(() -> {
                    log("start receive task");
                    mainHanlder.sendEvent(EVENT_ID_RECEIVE_START);
                    boolean result = RtmpUtil.receiveRtmp(getRtmpAddress(), getVideoFile().getAbsolutePath());
                    mainHanlder.sendEvent(InnerEvent.get(EVENT_ID_RECEIVE_FINISH, result));
                });
            } else {
                log("permission was not granted");
            }
        });
        textPushStatus = (Text) findComponentById(ResourceTable.Id_textPushStatus);
        findComponentById(ResourceTable.Id_btnPush).setClickedListener(component -> {
            String rtmp = getRtmpAddress();
            if (!checkIpValid(rtmp)) {
                showToast("rtmp服务地址不正确，请保存正确的地址");
                return;
            }
            File videoFile = getVideoFile();
            if (!videoFile.exists()) {
                showToast("需要推流的视频文件不存在，请先拉流后再推流");
                return;
            }
            if (checkPermission("ohos.permission.INTERNET") && checkPermission("ohos.permission.READ_USER_STORAGE")) {
                log("permission was granted");
                globalTaskDispatcher.asyncDispatch(() -> {
                    log("start push task");
                    mainHanlder.sendEvent(EVENT_ID_PUSH_START);
                    boolean result = RtmpUtil.pushRtmp(getRtmpAddress(), videoFile.getAbsolutePath());
                    mainHanlder.sendEvent(InnerEvent.get(EVENT_ID_PUSH_END, result));
                });
            } else {
                log("permission was not granted");
            }
        });
        TextField tfAddress = (TextField) findComponentById(ResourceTable.Id_tf_address);
        tfAddress.setText(getRtmpAddress());
        findComponentById(ResourceTable.Id_btnSave).setClickedListener(component -> {
            String value = tfAddress.getText();
            if (value == null || value.length() == 0) {
                showToast("地址不能为空");
                return;
            }
            if (!checkIpValid(value)) {
                showToast("请输入正确的rtmp服务器地址");
                return;
            }
            tfAddress.clearFocus();
            saveRtmpAddress(value);
            showToast("地址保存成功");
        });
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    private boolean checkPermission(String permission) {
        if (canRequestPermission(permission)) {
            requestPermissionsFromUser(new String[]{permission}, 0);
            return false;
        }
        return true;
    }

    private void initPreferences() {
        if (preferences == null) {
            preferences = new DatabaseHelper(this).getPreferences(PREF_NAME);
        }
    }

    /**
     * 获取rtmp服务器地址
     *
     * @return rtmp服务器地址，可能为空字符
     */
    private String getRtmpAddress() {
        initPreferences();
        return preferences.getString(KEY_SERVER, "");
    }

    /**
     * 保存rtmp服务器地址到本地文件
     *
     * @param address rtmp文件地址
     */
    private void saveRtmpAddress(String address) {
        initPreferences();
        preferences.putString(KEY_SERVER, address).flush();
    }

    /**
     * 检查地址有效性
     *
     * @param address rtmp服务器地址
     * @return true 表示地址有效，false表示地址无效
     */
    private boolean checkIpValid(String address) {
        return RtmpUtil.checkAddressValidity(address);
    }

    /**
     * 显示Toast
     *
     * @param msg 内容
     */
    private void showToast(String msg) {
        new ToastDialog(this).setText(msg).show();
        log(msg);
    }

    /**
     * 获取视频文件
     *
     * @return 视频文件
     */
    private File getVideoFile() {
        return new File(getContext().getExternalCacheDir(), FILENAME);
    }

    private void log(String msg) {
        HiLog.info(rtmpLabel, msg);
    }
}
